package com.zly.lab.blog.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Collection;
import java.util.Objects;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    DataSource dataSource;
    @Value("${COOKIE.VALIDITY}")
    private String COOKIE_VALIDITY;

    //访问控制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //1 自定义用户访问控制
        http.authorizeRequests()
                .antMatchers("/","/articleDetial/**","/page/**","/login","/toRegister","/utils/*","/register","/errorPage/comm/*").permitAll()
                .antMatchers("/article_img/**","/assets/**","/back/**","/user/**","/error").permitAll()//静态资源
                .antMatchers("/admin/**").hasRole("admin")//admin用户
                .antMatchers("/swagger-ui/**","/webjars/**","/swagger-resources/**","/v2/**","/v3/**").hasRole("admin")//swagger-ui
                .anyRequest().authenticated();
//        表单校验处理
        http.formLogin()
                .loginPage("/login")
                .usernameParameter("username")
                .passwordParameter("password")
                .successHandler((httpServletRequest, httpServletResponse, authentication) -> {
                    //1 获取到拦截页面
                    HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
                    //2 跳转到原始访问页
                    String url = httpServletRequest.getParameter("url");
                    SavedRequest savedRequest = requestCache.getRequest(httpServletRequest, httpServletResponse);
                    if(savedRequest!=null){
                        //跳转到拦截页面
                        httpServletResponse.sendRedirect(savedRequest.getRedirectUrl());
                    }else if(url!=null& !Objects.equals(url, "")){
                        //跳转到原始访问页
                        httpServletResponse.sendRedirect(url);
                    }else {
                        //跳转到主页
                        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
                        boolean isAdmin = authorities.contains(new SimpleGrantedAuthority("ROLE_admin"));
                        if(isAdmin){
                            //如果是管理员admin-->后台首页 /admin
                            httpServletResponse.sendRedirect("admin");
                        }else {
                            //如果不是管理员 -->前台首页  /
                            httpServletResponse.sendRedirect("index");
                        }
                    }
                })
                .failureHandler((httpServletRequest, httpServletResponse, e) -> {
                    //回到登录页面,重写登录     //获取原始访问路径
                    String url = httpServletRequest.getParameter("url");
                    httpServletResponse.sendRedirect("/login?error&url="+url);
                });
//        退出登录控制
        http.logout()
                .logoutUrl("/logout") // 退出的URL
                .logoutSuccessUrl("/"); // 成功退出的访问地址
        //4 是否要开启记住我功能,设置cookie有效时间
        http.rememberMe().alwaysRemember(true).tokenValiditySeconds(Integer.parseInt(COOKIE_VALIDITY));
        // 异常处理
        http.exceptionHandling().
                accessDeniedHandler((httpServletRequest, httpServletResponse, e) -> {
                    //跳转到自定义403页面
                    //发送跳转到403页面的请求
                    httpServletRequest
                            .getRequestDispatcher("/errorPage/comm/error_403")
                            .forward(httpServletRequest,httpServletResponse);
                }).
                authenticationEntryPoint((httpServletRequest, httpServletResponse, e) ->{   //跳转到自定义404页面
                    httpServletRequest
                            .getRequestDispatcher("/errorPage/comm/error_404")
                            .forward(httpServletRequest,httpServletResponse);
                });
    }

    //认证方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //JDBC方式认证:
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        // JDBC身份认证SQL
        //查询用户
        String userSQL = "select username,password,valid from user where username=?";
        //查询权限
        String authoritySQL = "select a.username,b.authority " +
                "from user a,authority b,user_authority c " +
                "where a.id=c.user_id and b.id=c.authority_id and username=?";
        auth.jdbcAuthentication()
                .passwordEncoder(encoder)
                .dataSource(dataSource)
                .usersByUsernameQuery(userSQL)
                .authoritiesByUsernameQuery(authoritySQL);
    }
}
